﻿//
//{
//     type: "list",// list batch row form
//     name: "出入库记录表(幼儿)",
//     fn: "出入库记录表(幼儿).xls",
//     search: "ItemID",  
//     where: { TypeOf: 2 },
//     action: "",//默认为list
//     actionOne:"", batch用到，默认为get
//     controller: "",//没有指定就取call定义上的
//     max:100,//最多导出记录数,默认1000条
// },
//

function getRptController(tb, rptType) {
    let tbname = tb.tbname;
    let call = ($mbh5? tb.call_h5: tb.call_pc) || tb.call;
    if (call) {
        if (["list", "batch"].indexOf(rptType) != -1) {
            call = call.list;
        } else {
            call = call.get;
        }
        if (call) {
            if (call.startsWith("/")) {
                tbname = call.split("/")[1];
            } else {
                tbname = call.split("/")[0];
            }
        }
    }
    return tbname || tb.tbname;
}

function getRptAction(tb, rptType) {
    let islist = (["list", "batch"].indexOf(rptType) != -1);
    let action = islist ? "list" : "get";
    let call = ($mbh5? tb.call_h5: tb.call_pc) || tb.call;
    if (call) {
        if (islist) {
            call = call.list;
            action = "list";
        } else {
            call = call.get;
            action = "get";
        }
        if (call) {
            if (call.startsWith("/")) {
                action = call.split("/")[2];
            } else {
                action = call.split("/")[1];
            }
        }
    }
    return action;
}

function parseRpt(tb, rpt) {
    if (!rpt.controller) {
        rpt.controller = getRptController(tb, rpt.type);
    }
    if (!rpt.action) {
        rpt.action = getRptAction(tb, rpt.type);
    }
    if (!rpt.name && rpt.fn) {
        rpt.name = rpt.fn.substr(0, rpt.fn.lastIndexOf("."));
    }
    if (rpt.type == "list" && rpt.name == "动态列导出") {
        rpt.where = dyncColWhere;
    }
}

/***
 *动态列导出，让用户选择需要导出的列，导出报表的名字必须为 【动态列导出】， 
 *无需指定模板文件名
 */
async function dyncColWhere(rpt, type) {
    if (type == "export") {
        let cols = this.$refs.grid.cols.map((x, ix) => {
            var item = {
                ID: ix,
                label: x.label,
                code: x.code,
                width: x.width || 200,
                format: "",
                _check: true
            };
            if (x.type == "date") {
                item.format = x.format || "yyyy-MM-dd"
            } else if (x.type == "datetime") {
                item.format = x.format || "yyyy-MM-dd HH:mm";
            } else if (x.type == "time") {
                item.format = x.format || "HH:mm";
            } else if (x.type == "boolean") {
                item.format = "[否,是]";
            } else if (x.type == "int" && x.options && x.options.length > 0) {
                let opt = [];
                for (let ix = 0; ix <= x.options.length; ix++) {
                    let v = x.options.find(x1 => x1.value == ix);
                    if (v) {
                        opt.push(v.label);
                    } else {
                        opt.push("");
                    }
                }
                //如果存在-1状态，放在最后面
                let v = x.options.find(x1 => x1.value == -1);
                if (v) {
                    opt.push(v.label);
                }

                item.format = "[" + opt.join(",") + "]";
            }
            return item;
        });

        let key = "_dynaCols_" + this.tbname;
        var lastCols = localStorage.getItem(key);
        if (lastCols) {
            lastCols = lastCols.split(";");
            let lastIx = 100;
            cols.forEach(col => {
                let ix = lastCols.indexOf(col.code);
                col._check = ix != -1;
                if (ix == -1) {
                    ix = lastIx;
                    lastIx++;
                }
                col._ix = ix;
            });
            cols.sort((a, b) => a._ix - b._ix);
        }


        let prop = {
            title: "选择需要导出的列",
            dlgName: "MySelectItemsDialog",
            modelValue: cols,
            cell: {
                title: "${label}"
            },
        };
        return $server.dlg.select(prop).then(items => {
            rpt.expFn = this.cfg.title + ".xls";
            rpt.fn = "动态列导出";
            let lastCols = items.map(x => x.code).join(";");
            let key = "_dynaCols_" + this.tbname;
            localStorage.setItem(key, lastCols);

            return { _dynaCols: items.map(x => `${x.code}|${x.label}|${x.width}|${x.format}`).join(";") };
        });
    }
}

function checkSearchField(search) {
    let ss = search.split(";").filter(p => p.length > 0);
    try {
        ss.forEach(key => {
            if (!this.search[key]) {
                let field = this.cfg.columns.find(p => p.code == key || p.searchCode == key);
                if (!field) {
                    field = this.cfg.search.find(p => p.code == key);
                }
                if (field) {
                    throw field.label;
                }
            }
        })
        return true;
    } catch (e) {
        $msg.alert("请输入：" + e);
        return false;
    }
}

function formatRptName(name, formData) {
    //输出的报表文件名，用字段值进行替换
    //${xxxx} 或者${xxx:yyy}  xxx 字段名 yyy格式 格式目前支持支日期时间
    return name.replaceAll(/\$\{([^\$\{\}]+)\}/g, function (tag, key) {
        let ix = key.indexOf(":");
        if (ix == -1) {
            return formData[key];
        }
        let fmt = key.substr(ix + 1);
        key = key.substr(0, ix);
        return mydate.formatDate(formData[key], fmt);
    })
}

async function doArchive(rpt, sort) {
    let res = await getActionAndParams.apply(this, [rpt, sort]);
    if (!res) return;
    this.$SelectFolder(function (fold, fullPath) {
        res.pm._folderID = fold.id;
        $server.call(res.action, res.pm).then(res => {
            $msg.notify("操作成功");
        })
    })
}

function proceWhereParams(search){

    if (search && search.FieldConditionArray) {
        delete search.FieldConditionArray;
    }
    let FieldConditionArray = [];
    if (search) {
        Object.keys(search).forEach(key => {
            if (["FieldConditionArray", "____key", "pageIndex", "pageSize"].indexOf(key) == -1) {
                let sval = search[key];
                if (sval) {
                    let sitem = { Name: key, Value: sval, TypeOf: 1 };
                    FieldConditionArray.push(sitem);
                }
            }
        })
    }
    if (FieldConditionArray.length > 0) {
        search.FieldConditionArray = FieldConditionArray;
    }
}

async function getActionAndParams(rpt, sort) {
    if (rpt.type == "list" && rpt.search) {
        if (!checkSearchField.apply(this, [rpt.search])) return;
    }
    let wherePm = {};
    if (rpt.where) {
        if (typeof (rpt.where) == "function") {
            wherePm = await rpt.where.apply(this, [rpt, "export", sort]);
        } else {
            wherePm = { ...rpt.where };
        }
    }
    if (rpt.type == "list") {
        let where = { ...this.search, ...wherePm };
        //自定义参数
        if (rpt.params) {
            if (typeof (rpt.params) == "function") {
                let pp = await rpt.params.apply(this);
                if (pp) {
                    where = Object.assign(where, pp);
                }
            } else {
                where = Object.assign(where, rpt.params);
            }
        }

        proceWhereParams(where);
        if (sort) {
            where.sort = sort;
        }
        where.pageIndex = 1;
        where.pageSize = rpt.max || 1000;

        let pm = {
            fn: rpt.fn,
            expFn: rpt.expFn || rpt.fn,
            controller: rpt.controller,
            action: rpt.action,
            jsonParams: JSON.stringify(where),
            preview: false,
        }
        return { action: "/Common/Export", pm: pm };
    } else if (rpt.type == "batch") {
        if (rpt.search) {
            if (!checkSearchField.apply(this, [rpt.search])) return;
        }
        let where = { ...this.search, ...wherePm };
        //自定义参数
        if (rpt.params) {
            if (typeof (rpt.params) == "function") {
                let pp = await rpt.params.apply(this);
                if (pp) {
                    where = Object.assign(where, pp);
                }
            } else {
                where = Object.assign(where, rpt.params);
            }
        }

        proceWhereParams(where);
        if (sort) {
            where.sort = sort;
        }
        where.pageIndex = 1;
        where.pageSize = rpt.max || 100;
        let tb = this.cfg;
        if(rpt.listParams && typeof(rpt.listParams)=="string" && rpt.listParams.startsWith("{")){
            rpt.listParams = JSON.parse(rpt.listParams);
        }
        if(rpt.oneParams && typeof(rpt.oneParams)=="string" && rpt.oneParams.startsWith("{")){
            rpt.oneParams = JSON.parse(rpt.oneParams);
        }
        return {
            action: "/Common/ExportBatch2", pm: {
                fn: rpt.fn,
                expFn: rpt.expFn || rpt.fn,
                controller: rpt.controller,
                listAction: rpt.listAction || rpt.action,
                oneAction: rpt.actionOne || rpt.oneAction || getRptAction(tb, "row"),
                listParams: JSON.stringify({...where, ...rpt.listParams}),
                oneParams: JSON.stringify({ id: "${id}", ...rpt.oneParams}),
                listField: rpt.listField || "Records",
                keyField: rpt.keyField || "ID",
                labelField: rpt.labelField || "${ID}",
            }
        };
    } else if (rpt.type.indexOf("row") != -1 || rpt.type.indexOf("form") != -1) {
        let pm = {
            fn: rpt.fn,
            expFn: formatRptName(rpt.expFn || rpt.fn, this.formData),
            controller: rpt.controller,
            action: rpt.action,
            jsonParams: JSON.stringify({...wherePm, id: this.formData.ID }),
            preview: false,
        }
        return { action: "/Common/Export", pm: pm }
    }
}

async function doExport(rpt, sort) {
    let res = await getActionAndParams.apply(this, [rpt, sort]);
    if (res) {
        return $server.download(res.action, res.pm);
    }
}

function doDownloadRpt(rpt) {
    //where方法里面可以修改模板 fn, controller...
    if (rpt.where && typeof (rpt.where) == "function") {
        rpt.where.apply(this, [rpt, "download"]);
    }
    let pm = {
        controller: rpt.controller,
        fn: rpt.fn
    }


    console.log("ctrl = " + window.event.ctrlKey);
    //如果检测到按下了ctrl键，则下载原始模板
    if (window.event.ctrlKey) {
        this.$download("/Common/downloadOriginalRptFile", pm);
    } else {
        //否则下载本园模板
        this.$download("/Common/downloadRptFile", pm);
    }
}

function doUploadRpt(rpt) {
    //where方法里面可以修改模板 fn, controller...
    if (rpt.where && typeof (rpt.where) == "function") {
        rpt.where.apply(this, [rpt, "upload"]);
    }

    let extData = {
        fn: rpt.fn,
        controller: rpt.controller,
    }
    let ext = extData.fn.substr(rpt.fn.lastIndexOf("."));
    let cfg = {
        url: "/Common/UploadForm2Tpl",
        accept: ext,
        extData
    }
    $server.upload(cfg).then(res => {
        $msg.alert("上传成功");
    })
}

async function getImportParams(rpt) {
    if (!rpt.url) {
        rpt.url = `/${rpt.controller}/${rpt.action}`;
    }
    let params = { url: rpt.url };
    if (rpt.where) {
        if (typeof (rpt.where) == "function") {
            let resParams = await rpt.where.apply(this, [rpt]);
            params = { ...params, ...resParams };
        } else if (typeof (rpt.where) == "object") {
            params = { ...params, ...rpt.where }
        }
    }

    if (rpt.fn) {
        let ext = rpt.fn.substr(rpt.fn.lastIndexOf("."));
        params.accept = "";
    }

    return params;
}

async function doImport(rpt) {
    let params = await getImportParams(rpt);

    return $server.upload(params).then(res => {
        this.loadData();
        $msg.alert("导入成功");
    })
}

function doDownloadImp(rpt) {
    let fn = rpt.fn;
    if (!fn.startsWith("/")) {
        if (fn.indexOf("/") != -1) {
            fn = `/Content/excel_report/${fn}`;
        } else {
            fn = `/Content/excel_report/${rpt.controller}/${fn}`;
        }
    }
    $server.downloadFile(fn, rpt.expFn);
}

async function doPreview(rpt, sort) {
    if (rpt.search) {
        if (!checkSearchField.apply(this, [rpt.search])) return;
    }
    let wherePm = {};
    if (rpt.where) {
        if (typeof (rpt.where) == "function") {
            wherePm = rpt.where.apply(this, [rpt, "preview", sort]);
        } else {
            wherePm = { ...rpt.where };
        }
    }
    let where = { ...this.search, ...wherePm };
    //自定义参数
    if (rpt.params && typeof (rpt.params) == "function") {
        let pp = await rpt.params.apply(this);
        if (pp) {
            where = Object.assign(where, pp);
        }
    }
    if (sort) {
        where.sort = sort;
    }
    where.pageIndex = 1;
    where.pageSize = rpt.max || 1000;
    let pm = {
        fn: rpt.fn,
        expFn: rpt.expFn || rpt.fn,
        controller: rpt.controller,
        action: rpt.action,
        jsonParams: JSON.stringify(where),
        preview: true,
    }
    $server.call("/Common/Export", pm).then(res => {
        let url = `/Common/printHtml?url=${res.url}&title=${rpt.name}`;
        window.open(url, "_blank");
    })
}

function makeListRpts(tb, rpts) {
    let op1 = [];
    let opImports = [];

    rpts.filter(p => p.type == "import")
        .forEach(p => {
            opImports.push(`导入【${p.name}】`);
            opImports.push(`下载导入模板【${p.name}】`);
        })

    rpts.filter(p => (p.type == "list" || p.type == "batch"))
        .filter(p => !p.mode || p.mode.indexOf("export") != -1)
        .forEach(p => {
            let allowAdd = true;
            //如果有定义vif函数，先执行，返回true才添加这个菜单
            if (p.vif && typeof (p.vif) == "function") {
                allowAdd = p.vif.apply(this);
            }
            if (allowAdd != false) {
                if (p.sort == true) {
                    op1.push(`导出【${p.name}】(正序)`)
                    op1.push(`导出【${p.name}】(逆序)`)
                } else {
                    op1.push(`导出【${p.name}】`)
                }
                if (p.archive == true || (typeof (p.archive) == "function" && p.archive.apply(this) == true)) {
                    op1.push(`归档【${p.name}】`)
                }
            }
        });

    if (opImports.length > 0) {
        if (op1.length > 0) {
            op1 = opImports.concat("-", op1);
        } else {
            op1 = opImports;
        }
    }

    if (op1.length == 0) {
        //单条记录报表
        if (!rpts.some(p => p.type.indexOf("row") != -1 || p.type.indexOf("form") != -1)) {
            return;
        }
    }

    let rpts2 = rpts.map(p => p);

    let batchRpt = rpts2.find(p => p.type == "batch");
    if (batchRpt) {
        let rowRpt = rpts2.find(p => p.type.indexOf("row") != -1 || p.type.indexOf("form") != -1);
        if (rowRpt && rowRpt.fn == batchRpt.fn) {
            rpts2.splice(rpts.indexOf(batchRpt), 1);
        }
    }

    let options = op1;
    //默认可以定制， 如果 custom=false则不允许下载和上传
    rpts2 = rpts2.filter(p => p.fn && p.type != "import" && (p.custom == undefined || p.custom != false));

    //同名模板文件去重
    let rpts21 = [];
    rpts2.forEach(p => {
        let r1 = rpts21.find(x => x.fn == p.fn);
        if (!r1) {
            rpts21.push(p);
        }
    });
    //同名模板去重
    let rpts3 = rpts21.map(x => x.name);

    if (rpts3.length > 0) {
        let op2 = rpts3.map(p => `下载模板【${p}】`);
        let op3 = rpts3.map(p => `上传模板【${p}】`);

        if (op1.length > 0) {
            options = op1.concat("-", op2, "-", op3).join(";");
        } else {
            options = op1.concat(op2, "-", op3).join(";");
        }
    }

    let btn = null;
    if (options.length == 1) {
        btn = {
            label: "导出",
            type: "primary",
            vif: rpts[0].vif,
            click() {
                doExport.apply(this, [rpts[0]]);
            }
        }
    } else if(options.length>1) {
        btn = {
            label: "导出",
            type: "primary",
            options: options,
            click(cmd) {
                let m = cmd.match(/【(.+)】/)
                let name = m[1];
                let m1 = cmd.match(/\((.+)\)$/)
                let sort = null;
                if (m1) {
                    sort = m1[1];
                }
                cmd = cmd.substr(0, cmd.indexOf("【"));
                let rpt = rpts.find(p => p.name == name);
                if (cmd == "导出") {
                    doExport.apply(this, [rpt, sort]);
                } else if (cmd == "下载模板") {
                    doDownloadRpt.apply(this, [rpt]);
                } else if (cmd == "上传模板") {
                    doUploadRpt.apply(this, [rpt]);
                } else if (cmd == "归档") {
                    doArchive.apply(this, [rpt, sort]);
                } else if (cmd == "导入") {
                    doImport.apply(this, [rpt]);
                } else if (cmd == "下载导入模板") {
                    doDownloadImp.apply(this, [rpt]);
                }
            }
        };

    }
    if(btn){
        tb.search_action = tb.search_action || [];
        tb.search_action.push(btn);
    }
}

function makePreviewListRpts(tb, rpts) {
    let rpts2 = rpts.filter(p => (p.type == "list" || p.type == "batch") && p.mode && p.mode.indexOf("preview") != -1);
    if (rpts2.length == 0) return;

    let options = [];
    rpts2.forEach(p => {
        if (p.sort == true) {
            options.push(p.name + "(正序)");
            options.push(p.name + "(倒序)");
        } else {
            options.push(p.name)
        }
    });
    let btn = {
        label: "预览",
        type: "primary",
        click(cmd) {
            if (options.length > 1) {
                let m1 = cmd.match(/\((.+)\)$/)
                let sort = null;
                if (m1) {
                    sort = m1[1];
                    cmd = cmd.substr(0, cmd.length - sort.length - 2);
                }
                let rpt = rpts2.find(p => p.name == cmd);
                rpt && doPreview.apply(this, [rpt, sort]);
            } else {
                let rpt = rpts2[0]
                doPreview.apply(this, [rpt]);
            }
        }
    };
    if (options.length > 1) {
        btn.options = options.join(";");
    }

    tb.search_action = tb.search_action || [];
    tb.search_action.push(btn);
}

function makeRowRpt(tb, rpt,customLabel) {
    if (typeof (tb.grid) == "string") {
        tb.grid = {
            fields: tb.grid
        }
    }
    let btn = {
        label: "导出"+(customLabel?rpt.name:""),
        type: "primary",
        vif: rpt.vif,
        click(row) {
            let me = { formData: row };
            doExport.apply(me, [rpt]);
        }
    };
    tb.grid.actions = tb.grid.actions || [];
    tb.grid.actions.push(btn);

}

function makeFormRpt(tb, rpt, customLabel) {
    if (!tb.form) return;

    //默认不支持H5版本导出功能， 除非rpt上专门制定 allowH5:true
    if ($mbh5 && !rpt.allowH5) return;

    let btn = {
        label: "导出"+(customLabel?rpt.name:""),
        type: "primary",
        vif: rpt.vif || function () { return this.formData.ID > 0 },
        click() {
            doExport.apply(this, [rpt]);
        }
    };
    tb.form.actions = tb.form.actions || [];
    tb.form.actions.push(btn);

    if (rpt.archive == true || (typeof (rpt.archive) == "function" && rpt.archive.apply(this) == true)) {
        let btn = {
            label: "归档",
            type: "primary",
            vif: rpt.vif || function () { return this.formData.ID > 0 },
            click() {
                doArchive.apply(this, [rpt]);
            }
        };
        tb.form.actions = tb.form.actions || [];
        tb.form.actions.push(btn);
    }
}

function process(tb) {
    if (!tb || !tb.reports) return;
    if (!Array.isArray(tb.reports)) {
        throw ("reports 必须是数组类型")
    }
    //如果已经有自定义导出按钮，则不再处理
    if (tb.search_action && tb.search_action.find(p => p.label == "导出" && p.name && p.name.length > 0)) return;

    tb.reports.forEach(rpt => parseRpt(tb, rpt));

    let options = tb.reports;

    makeListRpts(tb, tb.reports);

    makePreviewListRpts(tb, options);

    options = tb.reports.filter(p => p.type.indexOf("row") != -1);
    for (let i=0; i<options.length;i++) {
        makeRowRpt(tb, options[i], options.length>1);
    }

    options = tb.reports.filter(p => p.type.indexOf("form") != -1);
    for (let i=0; i<options.length;i++) {
        makeFormRpt(tb, options[i], options.length>1);
    }

}


export { process, getActionAndParams as getRptActionAndParams };